﻿//------------------------------------------------------------------------------------------------- 
// <copyright file="SmartSetupEngine.cs" company="Microsoft">
// Microsoft Public License (Ms-PL) - https://smartsetup.codeplex.com/license
// </copyright>
// <author>Steven Shan</author>
//-------------------------------------------------------------------------------------------------

namespace Microsoft.STEVSHAN.SmartSetup.Engine
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using Microsoft.STEVSHAN.SmartSetup.Common;
    using Microsoft.STEVSHAN.SmartSetup.Handlers;

    public sealed class SmartSetupEngine : ISmartSetupEngine
    {
        private IDictionary<ISetupIndex, ISetupHandler> _handlerDictionary;
        private ISetupProviderManager _setupProviderManager;

        public SmartSetupEngine()
            : base()
        {
            this._handlerDictionary = new Dictionary<ISetupIndex, ISetupHandler>();
            this._setupProviderManager = new SetupProviderManager();
        }

        public int Execute(ISetupItem setupItem)
        {
            return this.Handle(setupItem, this, this.CreateContext());
        }

        public int Execute(string path)
        {
            ISetupItem setupItem;

            if (!this._setupProviderManager.TryCreateSetupItem(path, out setupItem))
            {
                throw new Exception();
            }

            return this.Execute(setupItem);
        }

        public int Execute(Stream stream)
        {
            ISetupItem setupItem;

            if (!this._setupProviderManager.TryCreateSetupItem(stream, out setupItem))
            {
                throw new Exception();
            }

            return this.Execute(setupItem);
        }

        public int Handle(ISetupItem setupItem, ISmartSetupEngine smartSetupEngine, IContext context)
        {
            ISetupIndex setupIndex;
            ISetupHandler setupHandler;

            setupIndex = setupItem.GetSetupIndex();

            if (!this._handlerDictionary.TryGetValue(setupIndex, out setupHandler))
            {
                if ((this == smartSetupEngine) || (smartSetupEngine == null))
                {
                    throw new Exception();
                }
                else
                {
                    return smartSetupEngine.Handle(setupItem, smartSetupEngine, context);
                }
            }

            return setupHandler.Handle(setupItem, this, this.CreateContext());
        }

        private IContext CreateContext()
        {
            return new Context();
        }
    }
}